/// <reference path="../types/w.d.ts" />
class Visualizer {
  file:any = null;
  audioContext:any = null;
  source:any = null;

  /**
   * API接口
   * @private
   */
  private _prepareAPI() {
    window.AudioContext = window.AudioContext || window.webkitAudioContext || window.mozAudioContext || window.msAudioContext;
    window.requestAnimationFrame = window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.msRequestAnimationFrame;
    try {
      this.audioContext = new AudioContext();
    } catch (e) {
      console.log('并不支持AudioContext:(');
      console.log(e);
    }
  }

  /**
   * Ajax 获取文件
   * @param url
   */
  loadSound(url) {
    let request = new XMLHttpRequest();
    request.open('get', url, true);
    request.responseType = 'arraybuffer';
    request.onload = () => {
      this.file = request.response;
      this._prepareAPI();
      this._start();
    };
    request.send();
  }

  /**
   * 转码
   * @private
   */
  private _start() {
    let audioContext = this.audioContext;
    audioContext.decodeAudioData(this.file,
        buffer => this._visualize(audioContext, buffer),
        e => console.log('木有转码成功：' + e));
  }

  /**
   * 渲染音频, 播放
   * @param audioContext
   * @param buffer
   * @private
   */
  private _visualize(audioContext, buffer) {
    let audioBufferSouceNode = audioContext.createBufferSource(),
        analyser = audioContext.createAnalyser();
    audioBufferSouceNode.connect(analyser);
    analyser.connect(audioContext.destination);
    audioBufferSouceNode.buffer = buffer;
    audioBufferSouceNode.start(0);
    this._drawSpectrum(analyser);
  }

  /**
   * 绘制图谱
   * @param analyser
   * @private
   */
  private _drawSpectrum(analyser) {
    let canvas = document.getElementById('canvas'),
        WIDTH = canvas.width,
        HEIGHT = canvas.height,
        meterWidth = 10,
        capHeight = 2,
        meterNum = 800 / (10 + 2),
        capYPositionArray = [],  // 线帽
        capStyle = '#fff',
        ctx = canvas.getContext('2d'),
        gradient = ctx.createLinearGradient(0, 0, 0, 300);

    gradient.addColorStop(1, '#0f0');
    gradient.addColorStop(0.5, '#ff0');
    gradient.addColorStop(0, '#f00');

    requestAnimationFrame(function drawMeter() {
      let array = new Uint8Array(analyser.frequencyBinCount);
      analyser.getByteFrequencyData(array);

      let step = Math.round(array.length / meterNum); // 计算采样步长
      ctx.clearRect(0, 0, WIDTH, HEIGHT);

      for (let i = 0; i < meterNum; i++) {
        let value = array[i * step];
        if (capYPositionArray.length < Math.round(meterNum)) {
          capYPositionArray.push(value);
        }
        ctx.fileStyle = capStyle;
        if (value < capYPositionArray[i]) {
          ctx.fillRect(i * 12, HEIGHT - (--capYPositionArray[i]), meterWidth, capHeight);
        } else {
          ctx.fillRect(i * 12, HEIGHT - (--capYPositionArray[i]), meterWidth, capHeight);
          capYPositionArray[i] = value;
        }
        // 开始频谱
        ctx.fillStyle = gradient;
        ctx.fillRect(i * 12, HEIGHT - value + capHeight, meterWidth, HEIGHT);
      }
      requestAnimationFrame(drawMeter);
    });
  }
}